package com.json.smtest.SMUtils.SM2;

import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
 
public class SM2EncDecUtils {
 
	private static final Logger LOGGER = LoggerFactory.getLogger(SM2EncDecUtils.class);
    private static final String publicKeyName = "PUBLICKEY";
    private static final String privateKeyName = "PRIVATEKEY";
 


    private SM2EncDecUtils() {
    }
    
    
    /**
     * 获取公钥字符串数据
     * @return
     * @throws Exception
     */
    public static String getPublicKeys() throws Exception {
        return generateKeyPair().get(publicKeyName).trim();
    }
    
    
   
    /**
     * 判断key是否存在且有效
     * @return
     */
    private static boolean isCreateKeyPair() {
        return false;
    }
   
    /**

    
    /**
     * 获取私钥
     * @return
     */
    public static String getPrivateKey() {
        return generateKeyPair().get(privateKeyName).trim();
    }
    
    
    public static String decryptStringByJs(String encrypttext) {
        String text = decryptString(encrypttext);
        return text == null ? null : text;
    }
    public static String decryptString(String encrypttext) {
        if (StringUtils.isBlank(encrypttext)) {
            return null;
        } else {
            try {
            	String privateKey = getPrivateKey();
            	System.out.println("--------------privateKey  "+privateKey);
            	String plainTextEncripted = new String(SM2EncDecUtils.decrypt(Util.hexToByte(privateKey), Util.hexToByte(encrypttext)),"UTF-8");
                return plainTextEncripted;
            } catch (NullPointerException var3) {
                LOGGER.error("keyPair cannot be null.");
            } catch (Exception var4) {
            }
 
            return null;
        }
    }
    
    
    // 生成随机秘钥对
    public static Map<String, String> generateKeyPair() {
//        SM2 sm2 = SM2.Instance();
//        AsymmetricCipherKeyPair key = null;
//        while (true) {
////            key = sm2.ecc_key_pair_generator.generateKeyPair();
////            if (((ECPrivateKeyParameters) key.getPrivate()).getD().toByteArray().length == 32) {
////                break;
////            }
//        }
//        ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();
//        ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();
//        BigInteger privateKey = ecpriv.getD();
//        ECPoint publicKey = ecpub.getQ();
//        String pubk = Util.byteToHex(publicKey.getEncoded());
//        String prik = Util.byteToHex(privateKey.toByteArray());
//        System.out.println("公钥: " + pubk);
//        System.out.println("私钥: " + prik);
//
//
//
//        Map<String, String> result = new HashMap<>();
//
//        result.put(publicKeyName, pubk);
//        result.put(privateKeyName, prik);
//
//        return result;
        return null;
    }
 
    // 数据加密
    public static String encrypt(byte[] publicKey, byte[] data) throws IOException {
//        if (publicKey == null || publicKey.length == 0) {
//            return null;
//        }
//
//        if (data == null || data.length == 0) {
//            return null;
//        }
//
//        byte[] source = new byte[data.length];
//        System.arraycopy(data, 0, source, 0, data.length);
//        Cipher cipher = new Cipher();
//        SM2 sm2 = SM2.Instance();
//        ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey);
//        ECPoint c1 = cipher.Init_enc(sm2, userKey);
//        cipher.Encrypt(source);
//        byte[] c3 = new byte[32];
//        cipher.Dofinal(c3);
//        return new StringBuffer(Util.byteToHex(c1.getEncoded())).append(Util.byteToHex(c3)).append(Util.byteToHex(source)).toString();

        return null;
    }
 
    // 数据解密
    public static byte[] decrypt(byte[] privateKey, byte[] encryptedData) throws IOException {
//        if (privateKey == null || privateKey.length == 0) {
//            return null;
//        }
//
//        if (encryptedData == null || encryptedData.length == 0) {
//            return null;
//        }
//        // 加密字节数组转换为十六进制的字符串 长度变为encryptedData.length * 2
//        String data = Util.byteToHex(encryptedData);
//
//        byte[] c1Bytes = Util.hexToByte(data.substring(0, 130));
//        int c2Len = encryptedData.length - 97;
//        byte[] c3 = Util.hexToByte(data.substring(130, 130 + 64));
//        byte[] c2 = Util.hexToByte(data.substring(194, 194 + 2 * c2Len));
//
//        SM2 sm2 = SM2.Instance();
//        BigInteger userD = new BigInteger(1, privateKey);
//
//        // 通过C1实体字节来生成ECPoint
//        ECPoint c1 = sm2.ecc_curve.decodePoint(c1Bytes);
//        Cipher cipher = new Cipher();
//        cipher.Init_dec(userD, c1);
//        cipher.Decrypt(c2);
//        cipher.Dofinal(c3);
//
//        // 返回解密结果
//        return c2;
        return null;
    }
 
    public static void main(String[] args) throws Exception {

//        singleThreadTest();
//        mutiThreadTest();

        //生成密钥对
//        Map<String, String> result = generateKeyPair();
//        System.out.println(result);

        String pubKey = "04790CD9B7AE1753DF1D8C4C3C5B5A279CCDEEB3571D475BEAFB8F173BBF99F2A83F2C62D0F58E7435479AA91A485DB94DEC09A7635249F41E6B2A2DF1A4AC3AFF";
        String priKey = "184BDEDE9454183BF0A08992A695E7CA7522053606A90357F8B75D9B90D6E2D5";

        String test = "1234567890QAZwsx中国事实上！@#";

        String encrypt = SM2EncDecUtils.encrypt(Util.hexToByte(pubKey), test.getBytes(StandardCharsets.UTF_8));
        System.out.println("SM2公钥加密后字符串:"+encrypt);

        byte[] decrypt = SM2EncDecUtils.decrypt(Util.hexToByte(priKey), Util.hexToByte(encrypt));
        System.out.println("SM2私钥解密后字符串:"+new String(decrypt,StandardCharsets.UTF_8.toString()));

        System.out.println("------------------------分割线 以下错误示例---------------------------");
        /**
         * sm2 只能公钥加密私钥解密   不能私钥加密公钥解密
         */
//        String encrypt1 = SM2EncDecUtils.encrypt(Util.hexToByte(priKey), test.getBytes(StandardCharsets.UTF_8));
//        System.out.println("SM2私钥加密后字符串:"+encrypt1);
//
//        byte[] decrypt1 = SM2EncDecUtils.decrypt(Util.hexToByte(pubKey), Util.hexToByte(encrypt1));
//        System.out.println("SM2私钥解密后字符串:"+new String(decrypt1,StandardCharsets.UTF_8.toString()));

    }
 
    private static void singleThreadTest() throws Exception {
        String plainText = "hello fhm";
        byte[] sourceData = plainText.getBytes();
//        Map<String, String> keymap = generateKeyPair();
 
       
       /* String cipherText = SM2EncDecUtils.encrypt(Util.hexToByte(keymap.get(publicKeyName)), sourceData);
        System.out.println("加密前长度: " + plainText.length() + ";加密后长度: " + cipherText.length());
        String plainTextEncripted = new String(SM2EncDecUtils.decrypt(Util.hexToByte(keymap.get(privateKeyName)), Util.hexToByte(cipherText)));
       */
//        String pubKey = "043B5185559F153348271530209AE4DAD8818E7E8C7932D6623D37D16A2856C0FD7BE3C4F9236F915BFE0EFEFA014BCA19CCE9B9F1ED088CBEDA6752517970A40D";
//        String priKey = "05A83CA89D1D65F2849DBC7A92468032A53224B4B662FA8759BD81572B177C99";
        String pubKey = "04790CD9B7AE1753DF1D8C4C3C5B5A279CCDEEB3571D475BEAFB8F173BBF99F2A83F2C62D0F58E7435479AA91A485DB94DEC09A7635249F41E6B2A2DF1A4AC3AFF";
        String priKey = "184BDEDE9454183BF0A08992A695E7CA7522053606A90357F8B75D9B90D6E2D5";

        
        
//        String cipherText = SM2EncDecUtils.encrypt(Util.hexToByte(pubKey), sourceData);
//        System.out.println("ciphString长度: " + plainText.length() + ";加密后长度: " + cipherText.length());
        
//        cipherText = "04570021572715032FD61C069EBBD20A332D12556EB9437729DEA2A047D2FDEDD214B5AED8E5C356A63BF73D268E34AFA9EF80B8B74E8C1619BFA7A1F6F13E7550A3B519D008BEFE34CB58A3B526727B2472ECB28EDBC5767E2268977178AE623A54A763F4BAC440403B";
        String cipherText = "04c964115b4898176e62815237c69418f911983352e3306ea18b0ee56222f51609b8aa4424f5e02079cb879982e09bfcc4da54859c06368b0640feebdd466160587746be3a0600b9264cf2f473e3b38ba7ac18883651d3dfd54a3d3d97c662f0a61a8f28d52f69b79191";
        
        String plainTextEncripted = new String(SM2EncDecUtils.decrypt(Util.hexToByte(priKey), Util.hexToByte(cipherText)),"UTF-8");
        System.out.println("000000   "+plainTextEncripted);
    }
 
    private static void mutiThreadTest() {
        String plainText = "sourceText";
        byte[] sourceData = plainText.getBytes();
 
        Map<String, String> keymap = generateKeyPair();
        int counts = 10;
        for (int i = 0; i < counts; i++) {
            new Thread(() -> {
                try {
                    for (int j = 0; j < counts; j++) {
                        String cipherText = SM2EncDecUtils.encrypt(Util.hexToByte(keymap.get(publicKeyName)), sourceData);
                        if (!plainText.equals(new String(SM2EncDecUtils.decrypt(Util.hexToByte(keymap.get(privateKeyName)), Util.hexToByte(cipherText))))) {
                            System.out.println("------解密后同原文不一致:" + Thread.currentThread().getName() + "--------------");
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                System.out.println(" --------------->线程" + Thread.currentThread().getName() + "执行完成.---------------------");
            }
            ).start();
        }
    }
}